package yz.cp.back.auth.security.handler;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import yz.cp.back.auth.security.ImAuthenticationFilter;
import yz.cp.back.common.integration.IntegrationAuthentication;
import yz.cp.back.common.integration.IntegrationAuthenticationContext;
import yz.cp.back.common.integration.authenticator.IntegrationAuthenticator;
import yz.cp.back.common.res.ApiResult;
import yz.cp.back.common.utils.ServletUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection;

@Slf4j
public class AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
    private String defaultFailureUrl;
    private boolean forwardToDestination = false;
    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
    public AuthenticationFailureHandler() {
    }

    public AuthenticationFailureHandler(String defaultFailureUrl) {
        super(defaultFailureUrl);
    }

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
        if (!complete(request, response, e)) {
            if (ServletUtils.isAjaxRequest(request)) {
                ServletUtils.renderResult(response, ApiResult.Custom().failure(e.getMessage()).path(request.getRequestURI()));
            } else {
                if (this.defaultFailureUrl == null) {
                    this.logger.debug("No failure URL set, sending 401 Unauthorized error");
                    response.sendError(HttpStatus.UNAUTHORIZED.value(), e.getMessage());
                } else {
                    this.saveException(request, e);
                    if (this.forwardToDestination) {
                        this.logger.debug("Forwarding to " + this.defaultFailureUrl);
                        request.getRequestDispatcher(this.defaultFailureUrl).forward(request, response);
                    } else {
                        this.logger.debug("Redirecting to " + this.defaultFailureUrl);
                        this.redirectStrategy.sendRedirect(request, response, this.defaultFailureUrl);
                    }
                }
            }
        }
    }

    /**
     * 进行预处理
     *
     * @param auth
     */
    private boolean complete(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) {
        IntegrationAuthentication integrationAuthentication = IntegrationAuthenticationContext.get();
        if (integrationAuthentication == null) {
            integrationAuthentication = new IntegrationAuthentication();
        }
        Collection<IntegrationAuthenticator> authenticators = ImAuthenticationFilter.authenticators;
        if(authenticators!=null){
            for (IntegrationAuthenticator authenticator : authenticators) {
                if (authenticator.support(integrationAuthentication)) {
                    return authenticator.complete(request, response, null, e);
                }
            }
        }
        return false;
    }
}